package ru.ifmo.mlarinsky.classificator.model;

import java.util.*;
import ru.ifmo.mlarinsky.classificator.io.IOUtil;

import ru.ifmo.mlarinsky.classificator.io.InstrumentLoader;
import ru.ifmo.mlarinsky.classificator.math.MathUtil;

public class Instrument implements Comparable<Instrument> {

    private final String symbol;
    private final SortedMap<QuoteDate, Quote> quotes;
    private final QuoteDate lastDate;

    public Instrument(String symbol, SortedMap<QuoteDate, Quote> quotes) {
        this.symbol = symbol;
        this.quotes = quotes;
        this.lastDate = quotes.lastKey();
    }

    public String getSymbol() {
        return symbol;
    }

    public SortedMap<QuoteDate, Quote> getQuotes() {
        return quotes;
    }

    public Quote getQuote(QuoteDate date) {
        Quote quote = quotes.get(date);
        if (quote == null) {
            quote = getNextQuote(date);
        }
        return quote;
    }

    public double getDetermination(Instrument index, Date periodStart, int periodLength, int step) {
        if (index == null) {
            throw new IllegalArgumentException("Index must not be null");
        }

        Iterator<QuoteDate> dates = this.quotes.keySet().iterator();
        if (!dates.hasNext()) {
            throw new IllegalStateException("Instrument with empty quotes.");
        }

        List<Quote> instrumentQuotesForPeriod = new ArrayList<Quote>();
        List<Quote> indexQuotesForPeriod = new ArrayList<Quote>();

        QuoteDate date = dates.next();
        while (dates.hasNext() && (date.compareTo(periodStart) < 0 || index.getQuote(date) == null)) {
            date = dates.next();
        }

        if (date == null) {
            return Integer.MIN_VALUE;
        }

        String startDateString = date.toString();
        for (int i = 0; i < periodLength; i++) {
            Quote instrumentQuote = quotes.get(date);
            Quote indexQuote = index.getQuote(date);

            if (instrumentQuote != null && indexQuote != null) {
                instrumentQuotesForPeriod.add(instrumentQuote);
                indexQuotesForPeriod.add(indexQuote);
            }

            if (!dates.hasNext()) {
                break;
            }

            int stepCounter = step;
            while (dates.hasNext() && (stepCounter-- > 0 || index.getQuote(date) == null)) {
                date = dates.next();
            }
        }
        String endDateString = date.toString();

        double determination = MathUtil.determination(instrumentQuotesForPeriod, indexQuotesForPeriod);

//        System.out.println("\nCounting R2(" + symbol + ", " + index.getSymbol() + ")" +
//                ".\nPeriod: from " + startDateString + " to " + endDateString + ".");
//        System.out.print("Dates are: ");
//        for (Quote quote : indexQuotesForPeriod) {
//            System.out.print(quote.getDate() + ", ");
//        }
//        System.out.println("\nR2 = " + determination);

//        System.out.println("Instrument quotes:");
//        for (Quote quote : instrumentQuotesForPeriod) {
//            System.out.println(quote.getClosePrice());
//        }
//
//        System.out.println("\nIndex quote for period:");
//        for (Quote quote : indexQuotesForPeriod) {
//            System.out.println(quote.getClosePrice());
//        }

        return determination/* > 30 ? 1 : 0*/;
    }

    public int compareTo(Instrument o) {
        return o != null ? symbol.compareTo(o.symbol) : 1;
    }

    public static void main(String[] args) throws Exception {
        List<Instrument> instruments = InstrumentLoader.loadInstruments(
                IOUtil.INSTRUMENTS_DATA_FILE_PATH, InstrumentLoader.Period.DEFAULT);
        Instrument instrument = instruments.get(0);
        SortedMap<QuoteDate, Quote> quotes = instrument.getQuotes();
        System.out.println(quotes.keySet().size());
    }

    private Quote getNextQuote(QuoteDate date) {
        long time = date.getTime();
        long day = 1000 * 60 * 60 * 24;

        Quote nextQuote = null;
        do {
            QuoteDate nextDate = new QuoteDate(new Date(time += day));
            nextQuote = quotes.get(nextDate);
        } while (nextQuote == null && time <= lastDate.getTime());

        return nextQuote;
    }
}
